// OgreDwarf.cpp : Defines the entry point for the application.
//

#include "stdinc.h"
#include <stdio.h>
#include <process.h>

#include <vector>

#include "..\OgreDwarf\hacked_vector"
#include "..\OgreDwarf\hacked_xstring"
#include "..\OgreDwarf\rebase.h"


//#include <string>

#include "..\OgreDwarf\DwarfFort\InternalStructures.h"
#include "LauncherLib.h"


DWORD WinMainLoc = 0x00518C70;
//#define __ASM_DEB
typedef  unsigned char uchar;
typedef unsigned short ushort;

#pragma pack(push,1)
struct OnePatch
{
#ifdef __ASM_DEB
	uchar int3;
#endif
	uchar pusha;
	uchar push1;
	DWORD OgreDwarfPtr;
	ushort call1;
	DWORD LoadLibraryPtr;
	uchar push2;
	DWORD CustWinMainPtr;
	uchar push_eax;
	ushort call2;
	DWORD GetProcAddressPtr;
	ushort call_eax;
	uchar popa;
	uchar retn;
	uchar OgreDwarfStr[12];
	uchar CustWinMainStr[12];
	
	OnePatch(DWORD insertionPoint, DWORD LL,DWORD GPA)
	{
		push1 = push2 = 0x68; call1 = call2 = 0x15FF;
		push_eax = 0x50;
		call_eax = 0xD0FF; retn = 0xC3;
		pusha = 0x60;popa = 0x61;
		strcpy((char*)OgreDwarfStr,"OgreDwarf");
		strcpy((char*)CustWinMainStr,"CustWinMain");
		LoadLibraryPtr = LL;
		GetProcAddressPtr = GPA;
		OgreDwarfPtr = insertionPoint + sizeof(OnePatch) - 24;
		CustWinMainPtr = insertionPoint + sizeof(OnePatch) - 12;
		
#ifdef __ASM_DEB
		int3 = 0xCC;
#endif
	}
};
#pragma pack(pop)


void FormatLastError()
{
		DWORD lastErr = GetLastError();
		CHAR errBuff[1024];
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,lastErr,0,errBuff,1024,(va_list*)NULL);
		MessageBox(NULL,errBuff,"Error!",MB_OK);
}


int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	/*char buf[256];
	itoa(sizeof(gCellDesignations)/ sizeof(CellDesignation),buf,10);
	MessageBox(NULL,buf,"a",MB_OK);
	return 0;*/

	STARTUPINFO si;
	memset(&si,0,sizeof(si));
	si.cb = sizeof(si);
	PROCESS_INFORMATION pi;
	memset(&pi,0,sizeof(pi));
	BOOL result; 

	
	result= CreateProcess("dwarfort.exe", "dwarfort.exe",NULL,NULL,FALSE,CREATE_SUSPENDED ,NULL,
		NULL,&si,&pi);
	if (result < 0)
	{
		FormatLastError();
		TerminateProcess(pi.hProcess,0);
		return 1;
	}
	DWORD GPA,LLA;
	

	if (FindLauncherFunctions(&pi,&GPA,&LLA) < 0)
	{
		TerminateThread(pi.hThread,-1);
		return -1;
	}

	OnePatch p(WinMainLoc,LLA ,GPA);
	DWORD oldProtect;
	SIZE_T bWritten;
	result = VirtualProtectEx(pi.hProcess,(LPVOID)WinMainLoc,sizeof(OnePatch),PAGE_EXECUTE_READWRITE,&oldProtect);
	if (result == 0)
	{
		FormatLastError();
		TerminateProcess(pi.hProcess,0);
		return 1;
	}
	result = WriteProcessMemory(pi.hProcess,(LPVOID)WinMainLoc,(LPVOID)&p,sizeof(OnePatch),&bWritten);
	if (result == 0)
	{
		FormatLastError();
		TerminateProcess(pi.hProcess,0);
		return 1;
	}
	if (bWritten != sizeof(OnePatch) ) 
	{
		MessageBox(NULL,"Injecting patch failed!","Error",MB_OK);
		TerminateProcess(pi.hProcess,0);
		return 1;
	}

	result = ResumeThread(pi.hThread);
	if (result < 0 )
	{
		FormatLastError();
		TerminateProcess(pi.hProcess,0);
		return 1;
	}


	return 0;
}

